﻿using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace TD.Interface
{
    internal static class Masking
    {
        public static Texture2D MaskString(Game game, ref Texture2D texture, Rectangle rectangle, String text)
        {
            SpriteBatch spriteBatch = new SpriteBatch(game.GraphicsDevice);
            SpriteFont font = game.Content.Load<SpriteFont>("interface\\MaskFont");

            // Create a new target to draw too.
            RenderTarget2D target = new RenderTarget2D(game.GraphicsDevice, texture.Width, texture.Height);
            {
                // Set the target of the device to our just created target.
                game.GraphicsDevice.SetRenderTarget(target);

                // Clear the background to black. (We need black and white for the mask to work!)
                game.GraphicsDevice.Clear(Color.Black);

                // Draw the string to the target.
                spriteBatch.Begin();
                spriteBatch.DrawString(font, text, new Vector2(rectangle.X, rectangle.Y), Color.White);
                spriteBatch.End();

                // Set the target to its original value.
                game.GraphicsDevice.SetRenderTarget(null);
            }

            // Create a texture that is able to hold the result of the draw.
            Texture2D fontTexture = new Texture2D(game.GraphicsDevice, target.Width, target.Height);

            // Copy the color from the target to the texture.
            Color[] data = new Color[target.Width * target.Height];
            target.GetData<Color>(data, 0, data.Length);
            fontTexture.SetData<Color>(data);

            // Release the target
            target.Dispose();

            // Now mask the original texture with the mask texture.
            Texture2D result = MaskTexture(game.GraphicsDevice, ref texture, ref fontTexture, rectangle);

            // Release the font texture, there is no need for it anymore.
            if (fontTexture != null)
                fontTexture.Dispose();

            return result;
        }

        /// <summary>
        /// Creates a masked texture rendered from the given input.
        /// </summary>
        /// <param name="graphicsDevice">The device for which to load the texture.</param>
        /// <param name="textureRGB">The texture from whom to get the RGB values.</param>
        /// <param name="textureA">The texture from whom to get the R value.</param>
        /// <param name="rectangle">The region on the rectangle to mask.</param>
        /// <returns>The result of applying the mask.</returns>
        /// <exception cref="System.ArgumentException" />
        public static Texture2D MaskTexture(GraphicsDevice graphicsDevice, ref Texture2D textureRGB, ref Texture2D textureA, Rectangle rectangle)
        {
            // Ensure the size of the textures is the same.
            if (textureA.Width != textureRGB.Width || textureA.Height != textureRGB.Height)
                throw new ArgumentException("The given textures do not match in size.");

            // Create an texture that is capable of holding the texture.
            Texture2D textureResult = new Texture2D(graphicsDevice, rectangle.Width, rectangle.Height);

            // Create room to store the colors.
            Color[] rgb = new Color[textureRGB.Width * textureRGB.Height];
            Color[] a = new Color[textureA.Width * textureA.Height];
            Color[] result = new Color[rectangle.Width * rectangle.Height];

            // Store the colors of both the source textures.
            textureRGB.GetData<Color>(rgb);
            textureA.GetData<Color>(a);

            // Transfer the colors to temporary array.
            for (int y = rectangle.Y; y < (rectangle.Y + rectangle.Height); y++)
            {
                for (int x = rectangle.X; x < (rectangle.X + rectangle.Width); x++)
                {
                    int idx = ((y * textureA.Width) + x);
                    result[((y - rectangle.Y) * rectangle.Width) + (x - rectangle.X)] = Color.FromNonPremultiplied(rgb[idx].R, rgb[idx].G, rgb[idx].B, a[idx].R);
                }
            }

            // Store the colors into the texture.
            textureResult.SetData<Color>(result);

            // Return the resulting texture.
            return textureResult;
        }
    }
}
